package com.jsits.v2x.common.util;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

/**
 * 基于mybatis批量处理工具
 * @author wn
 * @param <T>
 */
public class BatchOperateUtil<T> {

    private static Logger log = LoggerFactory.getLogger(BatchOperateUtil.class);

    /**
     * 批量插入（带条件的）
     *
     * @param object
     * @param clazz
     * @param count
     */
    public boolean batchInsert(List<T> object, Class<? extends Mapper<T>> clazz, int count, SqlSessionFactory sqlSessionFactory) {
        return this.doBatchInsert(object, clazz, count, sqlSessionFactory, 0);
    }


    private boolean doBatchInsert(List<T> object, Class<? extends Mapper<T>> clazz, int count, SqlSessionFactory sqlSessionFactory, int start) {
        boolean success = true;
        //获取一个批量的，不自动提交的session
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        Mapper<T> map = session.getMapper(clazz);
        int size = object.size();
        int i = start;
        try {
            for (i = start; i < size; i++) {
                map.insertSelective(object.get(i));
                if (i % count == 0 || i == size - 1) {
                    session.commit();
                    session.clearCache();
                }
            }
        } catch (Exception e) {
            success = false;
            log.error(e.getMessage());
            //session.rollback();
            this.doBatchInsert(object, clazz, count, sqlSessionFactory, i + 1);
        } finally {
            session.close();
        }
        return success;
    }

    /**
     * 批量插入（不带条件的）
     *
     * @param object
     * @param clazz
     * @param count
     */
    public boolean batchInsertNoCondition(List<T> object, Class<? extends Mapper<T>> clazz, int count, SqlSessionFactory sqlSessionFactory) {
        boolean success = true;
        //获取一个批量的，不自动提交的session
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        Mapper<T> map = session.getMapper(clazz);
        int size = object.size();
        try {
            for (int i = 0; i < size; i++) {
                map.insert(object.get(i));
                if (i % count == 0 || i == size - 1) {
                    session.commit();
                    session.clearCache();
                }
            }
        } catch (Exception e) {
            success = false;
            log.info(e.getMessage());
            session.rollback();
        } finally {
            session.close();
        }
        return success;
    }

    /**
     * 批量更新（带条件的）
     *
     * @param object
     * @param clazz
     * @param count
     */
    public boolean batchUpdate(List<T> object, Class<? extends Mapper<T>> clazz, int count, SqlSessionFactory sqlSessionFactory) {
        return this.doBatchUpdate(object, clazz, count, sqlSessionFactory, 0);
    }

    public boolean doBatchUpdate(List<T> object, Class<? extends Mapper<T>> clazz, int count, SqlSessionFactory sqlSessionFactory, int start) {
        boolean success = true;
        //获取一个批量的，不自动提交的session
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        Mapper<T> map = session.getMapper(clazz);
        int size = object.size();
        int i = start;
        try {
            for (i = start; i < size; i++) {
                map.updateByPrimaryKeySelective(object.get(i));
                if (i % count == 0 || i == size - 1) {
                    session.commit();
                    session.clearCache();
                }
            }
        } catch (Exception e) {
            success = false;
            log.error(e.getMessage());
            //session.rollback();
            this.doBatchUpdate(object, clazz, count, sqlSessionFactory, i + 1);
        } finally {
            session.close();
        }
        return success;
    }

    /**
     * 批量更新（不带条件的）
     *
     * @param object
     * @param clazz
     * @param count
     */
    public boolean batchUpdateNoCondition(List<T> object, Class<? extends Mapper<T>> clazz, int count, SqlSessionFactory sqlSessionFactory) {
        boolean success = true;
        //获取一个批量的，不自动提交的session
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        Mapper<T> map = session.getMapper(clazz);
        int size = object.size();
        try {
            for (int i = 0; i < size; i++) {
                map.updateByPrimaryKey(object.get(i));
                if (i % count == 0 || i == size - 1) {
                    session.commit();
                    session.clearCache();
                }
            }
        } catch (Exception e) {
            success = false;
            log.info(e.getMessage());
            session.rollback();
        } finally {
            session.close();
        }
        return success;
    }

    /**
     * 批量删除
     *
     * @param object
     * @param clazz
     * @param count
     */
    public boolean batchDelete(List<T> object, Class<? extends Mapper<T>> clazz, int count, SqlSessionFactory sqlSessionFactory) {
        boolean success = true;
        //获取一个批量的，不自动提交的session
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        Mapper<T> map = session.getMapper(clazz);
        int size = object.size();
        try {
            for (int i = 0; i < size; i++) {
                map.delete(object.get(i));
                if (i % count == 0 || i == size - 1) {
                    session.commit();
                    session.clearCache();
                }
            }
        } catch (Exception e) {
            success = false;
            log.error(e.getMessage());
            session.rollback();
        } finally {
            session.close();
        }
        return success;
    }
}
